package com.sumainfor.common.config;

import com.alibaba.fastjson.JSONObject;
import com.sumainfor.common.Constants;
import com.sumainfor.common.base.ITenantSelect;
import com.sumainfor.common.entity.SysUserVo;
import com.sumainfor.common.entity.WxUserEntity;
import com.sumainfor.common.util.ContextUtils;
import com.sumainfor.common.util.JsonResult;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author PuaChen
 * @Create 2018-11-03 11:14
 */
public class RequestFilter implements Filter {

    private WebApplicationContext webApplicationContext;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (request.getMethod().equals(RequestMethod.OPTIONS.toString())) {
            return;
        }

        String code = request.getHeader(Constants.HEAD_TYPE);
        String path = request.getServletPath();
        if (isIgnoreUrlSuffix(path)) {
            ContextUtils.setHeadType(Constants.HeadType.Ignore.getCode());
            filterChain.doFilter(request, response);
            return;
        }
        if (StringUtils.isBlank(code)) {
            outErrorMessage(401, "Invalid Code", response);
            return;
        }
        if (Constants.HeadType.SYS.checkCode(Integer.valueOf(code))) {
            //拦截后端管理的
            this.checkSysFilter(request, response, code, filterChain);
            return;
        } else if (Constants.HeadType.WX.checkCode(Integer.valueOf(code))) {
            //拦截微信的
            this.checkWxFilter(request, response, code, filterChain);
            return;
        } else if (Constants.HeadType.Ignore.checkCode(Integer.valueOf(code))) {
            //忽略拦截
            filterChain.doFilter(request, response);
            return;
        } else {
            outErrorMessage(401, "NotFont Code Number", response);
            return;
        }

    }

    /**
     * 拦截后台的
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    public void checkSysFilter(HttpServletRequest request, HttpServletResponse response, String headType, FilterChain filterChain) throws IOException, ServletException {
        String header = getUserParams(request);
        if (StringUtils.isBlank(header)) {
            outErrorMessage(401, "Invalid Params", response);
            return;
        }
        ContextUtils.setUser(header, SysUserVo.class, Integer.valueOf(headType));
        filterChain.doFilter(request, response);
    }

    /**
     * 拦截微信的
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    private void checkWxFilter(HttpServletRequest request, HttpServletResponse response, String headType, FilterChain filterChain) throws IOException, ServletException {
        String openId = request.getHeader(Constants.HEAD_USER_ID);
        if (StringUtils.isNotBlank(openId)) {
            WxUserEntity info = null;
            //查询用户信息
            ITenantSelect service = webApplicationContext.getBean(ITenantSelect.class);

            try {
                info = service.getWxBaseInfo(openId);
            } catch (Exception e) {
                outErrorMessage(500, e.getMessage(), response);
                return;
            }
            if (info == null) {
                //outErrorMessage(500, "User Not Fount", response);
                ContextUtils.setHeadType(Integer.valueOf(headType));
                filterChain.doFilter(request, response);
                return;
            }
            ContextUtils.setUser(JSONObject.toJSONString(info), WxUserEntity.class, Integer.valueOf(headType));
        } else {
            ContextUtils.setHeadType(Integer.valueOf(headType));
        }
        filterChain.doFilter(request, response);
    }

    public void outErrorMessage(int code, String errorMessage, HttpServletResponse response) throws IOException {
        response.reset();
        PrintWriter writer = response.getWriter();
        writer.write(JsonResult.error(errorMessage, code).toJson());
        writer.flush();
        writer.close();
    }

    private String getUserParams(HttpServletRequest request) {
        String header = request.getHeader(Constants.HEAD_USER_ID);
        if (StringUtils.isBlank(header)) {
            header = request.getParameter(Constants.HEAD_USER_ID);
        }
        if (StringUtils.isNotBlank(header)) {
            header = new String(Base64.decodeBase64(header));
        }
        return header;
    }

    @Override
    public void destroy() {

    }

    /**
     * 判断是否有需要忽略的Url地址
     *
     * @param path
     * @return
     */
    private boolean isIgnoreUrlSuffix(String path) {
        for (String suffix : Constants.IGNORE_URL_SUFFIX) {
            if (path.endsWith(suffix)) {
                return true;
            }
        }
        return false;
    }
}
